package com.example.edu.Service.Impl;

import cn.hutool.json.JSONUtil;
import com.example.edu.Dto.ChatMessageDto;
import com.example.edu.Dto.MindMapUpdateDtoG;
import com.example.edu.Dto.PromptDto;
import com.example.edu.Dto.Return;
import com.example.edu.Entity.Chapter;
import com.example.edu.Entity.Document;
import com.example.edu.Entity.Mind_Map;
import com.example.edu.Entity.User;
import com.example.edu.Mapper.*;
import com.example.edu.Service.MindMapService;
import com.example.edu.Utils.AIUtil;
import com.example.edu.Utils.CacheDataBaseUtil;
import com.example.edu.Utils.JwtUtil;
import com.zhipu.oapi.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.edu.Utils.MyConstants.*;

@Service
public class MindMapServiceImpl implements MindMapService {
    @Resource
    ChapterMapper chapterMapper;
    @Resource
    CourseMapper courseMapper;
    @Resource
    Mind_MapMapper mind_mapMapper;
    @Resource
    DocumentMapper documentMapper;
    @Resource
    CacheDataBaseUtil cacheDataBaseUtil;
    @Resource
    AIUtil aiUtil;
    private static final Logger logger = LoggerFactory.getLogger(MindMapServiceImpl.class);

    @Override
    @Transactional
    public Return refresh(Integer documentId) {
        String[] messages = createCourseChapterMessage(documentId);
        String user_message = messages[0];
        user_message = user_message + MIND_MAP_USER_PROMPT1;
        List<String> user_messages = new ArrayList<>();
        user_messages.add(user_message);
        PromptDto prompt_data = addSystemMessage(user_messages,messages[1]);
        String result = aiUtil.getAnswer(prompt_data, 1, AI_MODEL_CODE[0]);
        if(result == null)
            return Return.fail(1,"出错了");
        result = JSONUtil.toJsonStr(JSONUtil.parse(result));
        try{
            return refresh1(documentId,result);
        } catch (Exception e){
            return Return.fail(1,"出错了");
        }
    }

    @Override
    @Transactional
    public Return update(MindMapUpdateDtoG mindMapUpdateData) {
        try{
            return update1(mindMapUpdateData);
        } catch (Exception e) {
            return Return.fail(1, "修改失败");
        }
    }

    @Override
    public Return get(Integer documentId) {
        String mindMap = cacheDataBaseUtil.selectById2(MIND_MAP_KEY, documentId,String.class, document_id -> mind_mapMapper.getMap(document_id));
        if(mindMap != null)
            return Return.ok(mindMap);
        return Return.fail(1,"还没有思维导图");
    }

    @Transactional
    public Return refresh1(int documentId,String result) {
        try{
            cacheDataBaseUtil.insert(MIND_MAP_KEY,documentId,result,new Mind_Map(documentId,-1,result),mind_map -> mind_mapMapper.updateMap(mind_map));
            return Return.ok(result);
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Return update1(MindMapUpdateDtoG mindMapUpdateData) {
        try{
            cacheDataBaseUtil.updateByObject(MIND_MAP_KEY,mindMapUpdateData.getDocument_id(),
                    new Mind_Map(mindMapUpdateData.getDocument_id(),-1,mindMapUpdateData.getMind_map()),mind_map -> mind_mapMapper.updateMap(mind_map));
            return Return.ok();
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Async
    @Transactional
    public void autoCreate(int userId,Integer courseId) {
        if(mind_mapMapper.getConnect(courseId) != null || !cacheDataBaseUtil.tryLock(MIND_MAP_KEY,courseId.toString(),LOCK_TTL,TimeUnit.MINUTES))
            return;
        PromptDto prompt_data = createPrompt(courseId);
        try {
            String result = aiUtil.getAnswer(prompt_data, 1,AI_MODEL_CODE[0]);
            if(result == null)
                return;
            result = JSONUtil.toJsonStr(JSONUtil.parse(result));
            Document document = new Document(0, "知识图谱", "mindMap",
                    userId, courseId, 0, 0, 0, 0, null,0,0,0);
            documentMapper.addDocument(document);
            cacheDataBaseUtil.insert(MIND_MAP_KEY, document.getDocument_id(),result,new Mind_Map(document.getDocument_id(),courseId,result), mind_map -> mind_mapMapper.addMap(mind_map));
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        } finally {
            cacheDataBaseUtil.unlock(MIND_MAP_KEY,courseId.toString());
        }
    }

    private PromptDto createPrompt(Integer courseId){
        String[] messages = createUserCourseMessage(courseId);
        String user_message = messages[0] + MIND_MAP_USER_PROMPT1;
        List<String> user_messages = new ArrayList<>();
        user_messages.add(user_message);
        return addSystemMessage(user_messages,messages[1]);
    }

    private String[] createUserCourseMessage(Integer courseId){
        List<String> chapter_names = chapterMapper.getChapters2(courseId);
        String course_name = courseMapper.getCourseName(courseId);
        StringBuilder user_message = new StringBuilder(String.format(MIND_MAP_COURSE_NAME_FORMAT, course_name));
        if(!chapter_names.isEmpty()) {
            for (String chapter_name : chapter_names)
                user_message.append(chapter_name).append(",");
        }
        return new String[]{user_message.toString(),course_name};
    }

    private PromptDto addSystemMessage(List<String> user_messages, String course_name){
        List<String> system_messages = new ArrayList<>();
        system_messages.add(SYSTEM_PROMPT2);
        system_messages.add(MIND_MAP_SYSTEM_PROMPT1);
        return new PromptDto(user_messages,system_messages,course_name);
    }

    private String[] createCourseChapterMessage(Integer documentId) {
        ChatMessageDto messageData = documentMapper.getMessageByDocumentId2(documentId);
        StringBuilder user_message;
        if(messageData.getChapter_name() != null && !messageData.getChapter_name().isEmpty())
            user_message = new StringBuilder(String.format(MIND_MAP_COURSE_CHAPTER_FORMAT, messageData.getCourse_name(), messageData.getChapter_name()));
        else {
            List<String> chapter_names = chapterMapper.getChapters2(messageData.getCourse_id());
            user_message = new StringBuilder(String.format(MIND_MAP_COURSE_NAME_FORMAT, messageData.getCourse_name()));
            if(!chapter_names.isEmpty()) {
                for (String chapter_name : chapter_names)
                    user_message.append(chapter_name).append(",");
            }
        }
        return new String[]{user_message.toString(),messageData.getCourse_name()};
    }
}
